home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * Copyright (c) 1990, 1991 Stanford University * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the name * Stanford may not be used in any advertising or publicity relating to * the software without the specific, prior written permission of * Stanford. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* $Header: /Source/Media/collab/TimeLine/RCS/appCanvas.c,v 1.1 92/05/29 14:39:32 drapeau Exp $ */ /* $Log: appCanvas.c,v $ * Revision 1.1 92/05/29 14:39:32 drapeau * Modified CheckDoubleClick() function to correct a few small errors. * The function now checks that some time has passed between the last * click and this one. It also uses more general (and safe) ways of * getting the timestamp of the current event, using XView functions. * These changes are the same as those in the Browse module's * CheckDoubleClick() function, which was originally taken from this * file and modified. * * Revision 1.0 91/09/30 16:48:53 chua * Update to version 1.0 * * Revision 0.48 91/09/25 13:45:55 chua * Changed the instrument field, instInfo, to editInfo. * * Revision 0.47 91/09/23 17:01:06 chua * In the event handler, set the selectedInstrument variable to the instrument * being clicked. * * Revision 0.46 91/09/19 17:28:36 chua * Make sure that variables are initialized properly. Change formatting slightly, * so that (if, for, while) statements with only one statement in them will not have * braces. * * Revision 0.45 91/09/16 14:37:09 chua * In RearrangeInst, reset the PANEL_CLIENT_DATA in accordance with the order that the * instrument is on the instrument list. * * Revision 0.44 91/08/22 12:11:28 chua * When checking for double click, make sure that the application is open before doing a * show application. * * Revision 0.43 91/08/21 16:50:34 chua * Include a new function, CheckDoubleClick, which is called from both * DrawCanvasEventHandler and AppCanvasEventHandler to determine if a double * click event has occurred. * * Modified AppCanvasEventHandler to take care of double click events. * A double click on an icon will bring the application to the front. * * Revision 0.42 91/08/16 16:55:14 chua * Moved the RearrangeInst function to the top of the file. * * Revision 0.41 91/08/09 15:10:54 chua * *** empty log message *** * * Revision 0.40 91/08/09 15:09:46 chua * This file contains the event and repaint handlers for the App canvas. (the canvas which * contains the application icons). * */ static char appCanvasrcsid[] = "$Header: /Source/Media/collab/TimeLine/RCS/appCanvas.c,v 1.1 92/05/29 14:39:32 drapeau Exp $"; #include "main.h" static int appY; /* Previous y position of the mouse in the app canvas when dragging. */ static int wasLeftDown; /* Keep track of whether the left mouse was click and/or dragged */ /* * This function will rearrange the positions of the applications in the instrument list (if necessary). * It first checks if there is a need to rearrange the applications. * If so, by making use of the parameters currentApp and yPos, pointers to the selected instrument node and the node where the mouse is on can be located. * The nodes are then moved around according to where the mouse was dragged. * Finally, the relative positions of each instrument node is updated to be consistent with their new position on the list. */ void RearrangeInst(tlFrame, currentApp, yPos) TimeLineFramePtr tlFrame; int currentApp; int yPos; { Instrument *moveInst, *prevInst; Instrument *currentInst; int top; int count; currentInst = (Instrument *) FindInstrument(currentApp, tlFrame); if (currentInst == NULL) return; top = 1; if (yPos > currentInst->cableStart) { if (currentApp + 1 == tlFrame->chosenApp) /* Moving to the same place. */ return; top = 0; } else if (currentApp == tlFrame->chosenApp + 1) /* Mouse on top half on icon and selected icon is the one above. No change in list */ return; if (top == 1) { currentApp --; if (currentApp >= 0) currentInst = (Instrument *) FindInstrument(currentApp, tlFrame); } prevInst = (Instrument *) FindInstrument(tlFrame->chosenApp - 1, tlFrame); moveInst = (Instrument *) FindInstrument(tlFrame->chosenApp, tlFrame); if (moveInst == NULL) return; if (prevInst == NULL) /* Remove the selected app from the list */ tlFrame->instHead = tlFrame->instHead->next; else prevInst->next = moveInst->next; if (currentApp < 0) /* Place the selected app in the new place */ { moveInst->next = tlFrame->instHead; tlFrame->instHead = moveInst; } else { moveInst->next = currentInst->next; currentInst->next = moveInst; } currentInst = tlFrame->instHead; count = 0; while (currentInst != NULL) /* Reassign the relative positions of each instrument by going down the list */ { currentInst->relativePosition = count; xv_set(currentInst->editInfo->NoteInfoList, /* Attach the instrument's relative position as the PANEL_CLIENT_DATA. */ PANEL_CLIENT_DATA, currentInst->relativePosition, /* Lets the program know which instrument the panel belongs to. */ NULL); currentInst->cableStart = (IconHeight + IconGap) * count + FirstCableYPosition; if (currentInst == moveInst) tlFrame->chosenApp = count; count ++; currentInst = currentInst->next; } AppCanvasRepaintHandler(tlFrame->TimeLine_window->AppCanvas, tlFrame->paintWinApp, /* Repaint the canvases to show the new positions */ tlFrame->dpyApp, tlFrame->xidApp, NULL); ShowNewCanvas(tlFrame, xv_get(tlFrame->DrawScrollbarHor, SCROLLBAR_VIEW_START)); } /* * Event callback function for `AppCanvas'. * This function will first check if the timeline is in stop mode and if the event triggering the calling of this function is * a button event. If not, it will return. * The function will then check which application has been chosen. * If the user has clicked at the bottom of the App canvas, where there is no application icon (the space in line with the timeline, the function * will not perform anything. * If the user has selected an icon, a check is made to see if the same icon has already been selected. * If so, it remains selected. * If not, the previously selected icon is redrawn so that it appears deselected (raised), and the newly selected icon is redrawn so that it * appears selected (sunken). * If the user drags the icon, the procedure RearrangeInst is called, which will rearrange the applications in the order that the user desired. */ Notify_value AppCanvasEventHandler(win, event, arg, type) Xv_window win; Event *event; Notify_arg arg; Notify_event_type type; { int tempChosenApp; /* The new chosen application */ char buf[100]; Instrument *currentInst; /* Pointer to the chosen instrument node */ TimeLineFramePtr tlFrame; TimeLine_window_objects *ip = (TimeLine_window_objects *) xv_get(win, XV_KEY_DATA, INSTANCE); tlFrame = TimeLineWindow[xv_get(ip->controls, PANEL_CLIENT_DATA)]; if (event_is_down(event) && tlFrame->status == StopMode && event_id(event) == MS_LEFT && tlFrame->numberOfApps > 0) { tempChosenApp = event_y(event) / (IconHeight + IconGap); /* Get the relative position of the mouse click, with respect to the height and spacing of the icons */ if ((tempChosenApp + 1) <= tlFrame->numberOfApps) { /* An application is now chosen */ currentInst = (Instrument *) FindInstrument(tempChosenApp, tlFrame); if (currentInst == NULL) return notify_next_event_func(win, (Notify_event) event, arg, type); tlFrame->selectedInstrument = currentInst; if (CheckDoubleClick(event, tlFrame) == OK && /* Check for double click */ strcmp(currentInst->port->hostName, "App not open") != 0) ShowApplicationHandler(tlFrame->TimeLine_window->appButton, MENU_NOTIFY); else { wasLeftDown = 1; appY = event_y(event) - IconHeight/2; if (tlFrame->chosenApp != tempChosenApp) { if (tlFrame->chosenApp >= 0) InstrumentDrawIcon(FindInstrument(tlFrame->chosenApp, tlFrame), Raised, tlFrame); /* Redraw the previously chosen app so that it is raised */ InstrumentDrawIcon(currentInst, Sunken, tlFrame); /* Draw the newly chosen app so that it is sunken */ sprintf (buf, "(%s)", currentInst->port->appName); xv_set (tlFrame->InsertBlankTimePopup->CurrentlyActiveTrackMsg, PANEL_LABEL_STRING, buf, NULL); tlFrame->chosenApp = tempChosenApp; } } } } else if (event_is_up(event)) /* Mouse up */ { if (wasLeftDown > 1) /* Perform the following only if there had been dragging */ { XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, IconXOffset, appY, IconHeight, IconHeight); wasLeftDown = 0; tempChosenApp = event_y(event) / (IconHeight + IconGap); if (tempChosenApp < 0) tempChosenApp = 0; else if (tempChosenApp >= tlFrame->numberOfApps) tempChosenApp = tlFrame->numberOfApps - 1; if (tempChosenApp != tlFrame->chosenApp) RearrangeInst(tlFrame, tempChosenApp, event_y(event)); } } else if (event_id(event) == LOC_DRAG && wasLeftDown) /* Dragging */ { if (wasLeftDown > 1) XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, IconXOffset, appY, IconHeight, IconHeight); wasLeftDown ++; appY = event_y(event); if (appY < 0) /* Set the lower and upper limits where the 'icon box' can move */ appY = 0; else if (appY > tlFrame->numberOfApps * (IconHeight + IconGap)) appY = tlFrame->numberOfApps * (IconHeight + IconGap); appY -= IconHeight/2; XDrawRectangle(tlFrame->dpyApp, tlFrame->xidApp, tlFrame->gcLine, IconXOffset, appY, IconHeight, IconHeight); } return notify_next_event_func(win, (Notify_event) event, arg, type); } /* * Repaint callback function for `AppCanvas'. * This function will set the height and width for the canvases, where appropriate. * It will then clear the AppCanvas and redraws all the instrument icons. */ void AppCanvasRepaintHandler(canvas, paint_window, display, xid, rects) Canvas canvas; Xv_window paint_window; Display *display; Window xid; Rectlist *rects; { Instrument *instrument; int type, instCount; TimeLineFramePtr tlFrame; TimeLine_window_objects *ip = (TimeLine_window_objects *) xv_get(canvas, XV_KEY_DATA, INSTANCE); tlFrame = TimeLineWindow[xv_get(ip->controls, PANEL_CLIENT_DATA)]; SetCanvasHeight(tlFrame); xv_set(tlFrame->TimeLine_window->AppCanvas, XV_WIDTH, 112, NULL); XClearWindow(tlFrame->dpyApp, tlFrame->xidApp); /* clear the whole display */ instCount = 0; for (instrument = tlFrame->instHead; instrument != NULL; instrument = instrument->next) /* draw the instrument icons */ { type = Raised; if (tlFrame->chosenApp == instCount) /* Check to see if the icon should be drawn raised or sunken */ type = Sunken; InstrumentDrawIcon (instrument, type, tlFrame); instCount++; } } /* * This function checks if a double click event has occurred. Both the time and mouse distance are taken into account. */ int CheckDoubleClick(event, tlFrame) Event *event; TimeLineFramePtr tlFrame; { static Event lastEvent; static int initial = 1; static int timeThreshold; short returnValue = Error; char *clickTimeout; int deltaTime; int deltaX, deltaY; struct timeval thisTime, lastTime; if (initial == 1) { timeThreshold = TimeThreshold; clickTimeout = XGetDefault((Display *) xv_get(tlFrame->TimeLine_window->window, XV_DISPLAY), "OpenWindows", "MultiClickTimeout"); /* Get the timeout value from the Xdefaults database */ if (clickTimeout != NULL) timeThreshold = atoi(clickTimeout) * 100; initial = 0; } if (event_is_up(event)) /* only deal with mouse down events */ return returnValue; if (event_action(event) == ACTION_SELECT && event_action(&lastEvent) == ACTION_SELECT ) { thisTime = event_time(event); lastTime = event_time(&lastEvent); deltaTime = (thisTime.tv_sec - lastTime.tv_sec) * 1000 + (thisTime.tv_usec - lastTime.tv_usec) / 1000; if ((deltaTime > 0) && (deltaTime <= timeThreshold)) /* Is the time within bounds? */ { deltaX = abs(event_x(&lastEvent) - event_x(event)); /* Check if the distance is within DistanceThreshold */ deltaY = abs(event_y(&lastEvent) - event_y(event)); if (deltaX <= DistanceThreshold && deltaY <= DistanceThreshold) returnValue = OK; } } lastEvent = *event; return returnValue; } /* end function CheckDoubleClick */